process.on('unhandledRejection', error => {
  // Will print "unhandledRejection {error}"
  console.error('unhandledRejection', error)
})

const express = require('express')
const { execute, subscribe } = require('graphql')
const { createServer } = require('http')

const bodyParser = require('body-parser')

const { graphqlExpress, graphiqlExpress } = require('apollo-server-express')

import jwt from 'jsonwebtoken'

import './constants'

import logger from './logger'
import CONFIG from './config'
import * as $wechat from './services/wechat'

const { schema, dataloaders } = require('./graphql')

var app = express()

import models from './models'
import services from './services'
import cors from 'cors'

// Initialize DataLoaders for each request
const initDataLoaders = context => {
  let loaders = {}
  for (let key in dataloaders) {
    let creator = dataloaders[key]
    if (typeof creator === 'function') {
      loaders[key] = creator(context)
    }
  }
  return loaders
}

app.use(logger)

app.use(cors())

app.use(
  '/graphql',
  bodyParser.json(),
  graphqlExpress(async (req, res) => {
    let user = null
    let { authorization } = req.headers
    if (typeof authorization === 'string') {
      authorization = authorization.split('Bearer')[1]
      if (typeof authorization === 'string' && authorization.length > 0) {
        authorization = authorization.trim()
        if (typeof authorization === 'string' && authorization.length > 0) {
          let authInfo = jwt.verify(authorization, CONFIG.jwt.secret)
          user = authInfo && authInfo.user
        }
      }
    }
    let dataloaders = initDataLoaders({ user })
    return {
      context: {
        user,
        models,
        services,
        dataloaders,
        config: CONFIG
      },
      schema
    }
  })
)

app.get(
  '/',
  graphiqlExpress({
    endpointURL: '/graphql'
  })
)

const PORT = CONFIG.app.port

const server = createServer(app)
server.listen(PORT, async () => {
  console.log(`ark graphql server running on port ${PORT}.`)
})
